﻿using System.Net;
using System.Net.Mail;
using System.Text;

namespace ApiLib.Helpers;

/// <summary>
/// 邮件工具类
/// </summary>
public class MailHelper
{
    private MailHelper _helper = new MailHelper();
    private MailConfig _config = new();
    private SmtpClient _client = new();

    private MailHelper()
    {
    }

    /// <summary>
    /// 获取实例
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public MailHelper GetInstance(MailConfig config)
    {
        var mailHelper = new MailHelper()
        {
            _config = config
        };
        //发件服务器身份凭证
        var network = new NetworkCredential
        {
            UserName = _config.From,
            Password = _config.FromPwd
        };
        //邮件传输协议
        _client = new SmtpClient();
        //smtp方式发送
        _client.Credentials = network;
        _client.EnableSsl = true;
        _client.Host = _config.ServerHost;
        _client.Port = _config.ServerPort;
        //发送成功后执行操作
        _client.SendCompleted += (sender, args) => { };
        return mailHelper;
    }

    /// <summary>
    /// 发送邮件
    /// </summary>
    /// <param name="message"></param>
    public void SendMail(SimpleMessage message)
    {
        message.CheckParam();
        //发件人邮箱地址（发件人地址必须与发件服务器账号地址一致）
        var from = new MailAddress(_config.From, _config.FromName, Encoding.UTF8);

        //邮件信息
        var mailMessage = new MailMessage();
        mailMessage.Priority = MailPriority.Normal;
        mailMessage.Subject = message.Subject.Trim();
        mailMessage.Body = message.Body;
        mailMessage.IsBodyHtml = true;
        //发信人地址可以不同，然后邮件的代发人为发件人（需要注意，不能为收件人地址，容易被识别为垃圾邮件）
        mailMessage.From = from;
        //邮件接收人
        if (message.To is { Count: > 0 })
        {
            foreach (var addr in message.To)
            {
                mailMessage.To.Add(addr);
            }
        }

        //邮件抄送()
        if (message.Cc is { Count: > 0 })
        {
            foreach (var addr in message.Cc)
            {
                mailMessage.CC.Add(addr);
            }
        }

        //密件抄送
        if (message.Bcc is { Count: > 0 })
        {
            foreach (var addr in message.Bcc)
            {
                mailMessage.Bcc.Add(addr);
            }
        }

        //附件集合
        if (message.Files is { Count: > 0 })
        {
            foreach (var att in message.Files.Select(filepath => new Attachment(filepath)))
            {
                mailMessage.Attachments.Add(att);
            }
        }

        _client.SendMailAsync(mailMessage);
    }

    /// <summary>
    /// 邮件配置
    /// </summary>
    public class MailConfig
    {
        /// <summary>
        /// 服务器地址
        /// </summary>
        public string ServerHost { get; set; } = "smtp.qq.com";

        /// <summary>
        /// 服务器端口
        /// </summary>
        public int ServerPort { get; set; } = 587;

        /// <summary>
        /// 发件人
        /// </summary>
        public string From { get; set; } = "";

        /// <summary>
        /// 发件人名称
        /// </summary>
        public string FromName { get; set; } = "发件人";

        /// <summary>
        /// 发件人密码
        /// </summary>
        public string FromPwd { get; set; } = "";
    }

    /// <summary>
    /// 简单短信
    /// </summary>
    public class SimpleMessage
    {
        /// <summary>
        /// 收件人
        /// </summary>
        public List<string>? To { get; set; }

        /// <summary>
        /// 抄送人
        /// </summary>
        public List<string>? Cc { get; set; }

        /// <summary>
        /// 密送
        /// </summary>
        public List<string>? Bcc { get; set; }

        /// <summary>
        /// 主题
        /// </summary>
        public string Subject { get; set; }

        /// <summary>
        /// 内容
        /// </summary>
        public string Body { get; set; }

        /// <summary>
        /// 附件
        /// </summary>
        public List<string>? Files { get; set; }

        /// <summary>
        /// 检查参数
        /// </summary>
        /// <exception cref="Exception"></exception>
        public void CheckParam()
        {
            if (string.IsNullOrEmpty(Subject))
            {
                throw new Exception("主题不能为空");
            }

            if (To == null || To.Count == 0)
            {
                throw new Exception("收件人不能为空");
            }
        }
    }
}